﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace EasyNet
{
    public static class DES
    {
        private static byte[] desIv = new byte[] { 0xF, 0x56, 0x52, 0xCD, 0xFF, 0x3F, 0x5D, 0x4 };
        /// <summary>
        /// DES加密字符串
        /// </summary>
        /// <param name="str_">待加密的字符串</param>
        /// <param name="s_key">加密密钥,要求为8位</param>
        /// <returns>返回加密后的字符串</returns>
        public static string EncryptString(string str_, string s_key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = Encoding.Default.GetBytes(str_);
            des.Key = ASCIIEncoding.ASCII.GetBytes(s_key);// 密匙
            des.IV = ASCIIEncoding.ASCII.GetBytes(s_key);// 初始化向量
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            var retB = Convert.ToBase64String(ms.ToArray());
            return retB;
        }

        /// <summary>
        /// DES解密字符串
        /// </summary>
        /// <param name="p_to_decrypt">待解密的字符串</param>
        /// <param name="s_key">解密密钥,要求为8位</param>
        /// <returns>返回解密后的字符串</returns>
        public static string DecryptString(string p_to_decrypt, string s_key)
        {
            if (IsBase64(p_to_decrypt))
            {
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                byte[] inputByteArray = Convert.FromBase64String(p_to_decrypt);
                des.Key = ASCIIEncoding.ASCII.GetBytes(s_key);
                des.IV = ASCIIEncoding.ASCII.GetBytes(s_key);
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                // 如果两次密匙不一样，这一步可能会引发异常
                cs.FlushFinalBlock();
                return System.Text.Encoding.Default.GetString(ms.ToArray());
            }
            return "";
        }
        /// <summary>
        /// 对字节数组进行加密
        /// </summary>
        /// <param name="src_bs">需要加密的字节数组对象</param>
        /// <param name="key_"></param>
        /// <returns>返回加密过的字节数组</returns>
        public static byte[] EnByteToByte(byte[] src_bs, int key_)
        {
            string desKeyStr = key_.ToString();
            byte[] desKey = System.Text.Encoding.UTF8.GetBytes(desKeyStr.Substring(0, 8));

            MemoryStream ins = new MemoryStream(src_bs);
            MemoryStream outs = new MemoryStream();
            outs.SetLength(0);

            byte[] buffer = new byte[1024 * 512];
            long readLen = 0;
            long totlen = ins.Length;
            int len;

            System.Security.Cryptography.DES des = new DESCryptoServiceProvider();
            CryptoStream encStream = new CryptoStream(outs, des.CreateEncryptor(desKey, desIv), CryptoStreamMode.Write);

            while (readLen < totlen)
            {
                len = ins.Read(buffer, 0, buffer.Length);
                encStream.Write(buffer, 0, len);
                readLen += len;
            }
            encStream.Close();
            outs.Close();
            ins.Close();

            return outs.ToArray();
        }

        /// <summary>
        /// 解密字节数组
        /// </summary>
        /// <param name="src_bs"></param>
        /// <param name="key_"></param>
        /// <returns></returns>
        public static byte[] DeEnByteToByte(byte[] src_bs, int key_)
        {
            string desKeyStr = key_.ToString();
            byte[] desKey = System.Text.Encoding.UTF8.GetBytes(desKeyStr.Substring(0, 8));

            MemoryStream ins = new MemoryStream(src_bs);
            MemoryStream outs = new MemoryStream();
            outs.SetLength(0);

            byte[] buffer = new byte[1024 * 512];
            long readLen = 0;
            long totlen = ins.Length;
            int len;

            System.Security.Cryptography.DES des = new DESCryptoServiceProvider();
            CryptoStream encStream = new CryptoStream(outs, des.CreateDecryptor(desKey, desIv), CryptoStreamMode.Write);

            while (readLen < totlen)
            {
                len = ins.Read(buffer, 0, buffer.Length);
                encStream.Write(buffer, 0, len);
                readLen += len;
            }
            encStream.Close();
            outs.Close();
            ins.Close();

            return outs.ToArray();
        }
        /// <summary>
        /// 传入需要加密的文件地址，生成新的加密后的文件
        /// </summary>
        /// <param name="in_file_path">需要加密的文件路径</param>
        /// <param name="out_file_path">生成的加密过的文件</param>
        /// <param name="key_">加密秘钥</param>
        public static void enFile(string in_file_path, string out_file_path, int key_)
        {
            string desKeyStr = key_.ToString();
            byte[] desKey = System.Text.Encoding.UTF8.GetBytes(desKeyStr.Substring(0, 8));
            FileStream ins = new FileStream(in_file_path, FileMode.Open, FileAccess.Read);
            FileStream outs = new FileStream(out_file_path, FileMode.OpenOrCreate, FileAccess.Write);
            outs.SetLength(0);

            byte[] buffer = new byte[1024 * 512];
            long readLen = 0;
            long totlen = ins.Length;
            int len;

            System.Security.Cryptography.DES des = new DESCryptoServiceProvider();
            CryptoStream encStream = new CryptoStream(outs, des.CreateEncryptor(desKey, desIv), CryptoStreamMode.Write);

            while (readLen < totlen)
            {
                len = ins.Read(buffer, 0, buffer.Length);
                encStream.Write(buffer, 0, len);
                readLen += len;
            }
            encStream.Close();
            outs.Close();
            ins.Close();
        }

        /// <summary>
        /// 传入需要解密的文件地址，生成解密后的文件
        /// </summary>
        /// <param name="in_file_path">需解密的文件</param>
        /// <param name="out_file_path">生成新的解密后的文件</param>
        /// <param name="key_">秘钥和加密时的一致</param>
        public static void DeFile(string in_file_path, string out_file_path, int key_)
        {
            string desKeyStr = key_.ToString();
            byte[] desKey = System.Text.Encoding.UTF8.GetBytes(desKeyStr.Substring(0, 8));
            FileStream ins = new FileStream(in_file_path, FileMode.Open, FileAccess.Read);
            FileStream outs = new FileStream(out_file_path, FileMode.OpenOrCreate, FileAccess.Write);
            outs.SetLength(0);

            byte[] buffer = new byte[1024 * 512];
            long readLen = 0;
            long totlLen = ins.Length;
            int len;

            System.Security.Cryptography.DES des = new DESCryptoServiceProvider();
            CryptoStream dencStream = new CryptoStream(outs, des.CreateDecryptor(desKey, desIv), CryptoStreamMode.Write);

            while (readLen < totlLen)
            {
                len = ins.Read(buffer, 0, buffer.Length);
                dencStream.Write(buffer, 0, len);
                readLen += len;
            }
            try
            {
                dencStream.Close();
            }
            catch (Exception exception)
            {

            }
            outs.Close();
            ins.Close();
        }
        /// <summary>  
        /// 是否是Base64字符串  
        /// </summary>  
        /// <param name="e_str"></param>  
        /// <returns></returns>  
        public static bool IsBase64(string e_str)
        {
            if ((e_str.Length % 4) != 0)
            {
                return false;
            }
            if (!Regex.IsMatch(e_str, "^[A-Z0-9/+=]*$", RegexOptions.IgnoreCase))
            {
                return false;
            }
            return true;
        }
    }
}
